package persistence;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.Vector;

import net.GameManagement;

import valueObjects.game.Player;
import valueObjects.game.card.Card;
import valueObjects.game.card.door.CharacterClassCard;
import valueObjects.game.card.door.CharacterRaceCard;
import valueObjects.game.card.door.CurseCard;
import valueObjects.game.card.door.MonsterCard;
import valueObjects.game.card.treasure.BuffCard;
import valueObjects.game.card.treasure.EquipmentCard;
import valueObjects.game.card.treasure.MiscellaneousCard;

public class FilePersistenceManager implements IPersistenceManager {

	private BufferedReader reader;
	
	private ObjectOutputStream oos;
	
	private ObjectInputStream ois;

	/**
	 * Buffered reader
	 */
	public void openForReading(String datei) throws IOException {
		this.reader = new BufferedReader(new FileReader(datei));
	}
	
	/**
	 * Saves serializable content to a .txt file
	 */
	public void openForReadingSer(String datenquelle) throws IOException {
		this.ois = new ObjectInputStream(new FileInputStream(datenquelle));
	}

	/**
	 * Currently not used
	 */
	public void openForWritingSer(String datei) throws IOException {
		this.oos = new ObjectOutputStream(new FileOutputStream(datei)); 
	} 

	/**
	 * Closes and flushes the streams
	 */
	public boolean close() {
		if (oos != null){
			try {
				oos.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				return false;
			}
		}
		
		if (ois != null){
			try {
				ois.close();
			} catch (IOException e1) {
				e1.printStackTrace();
				return false;
			}
		}

		if (reader != null) {
			try {
				reader.close();
			} catch (IOException e) {
				e.printStackTrace();
				return false;
			}
		}

		return true;
	}

	/**
	 * Reads and sets the values of an equip card from the EquipCards.txt file and returns the card
	 */
	public Card loadEquipCard() throws IOException {
		EquipmentCard equipCard = new EquipmentCard();
		
		String line = this.readLine();
		if(line == null) return null;
		String cardValues[] = line.split(";");
		
		if(cardValues[0].equals("#")){
			return equipCard;
		}
		
		try {
			equipCard.setLabel(cardValues[0]);
			equipCard.setDescription(cardValues[1]);
			equipCard.setValue(Short.parseShort(cardValues[2]));
			equipCard.setBig(Short.parseShort(cardValues[3]));
			equipCard.setPrice(Short.parseShort(cardValues[4]));
			equipCard.setInformation(cardValues[5]);
			equipCard.setSlot(cardValues[6]);
			equipCard.setUsability(cardValues[7]);
			equipCard.setAvailable(Short.parseShort(cardValues[8]));
			equipCard.setSmallIcon(DataFiles.getSmallIcon(equipCard));
			equipCard.setBackIcon(DataFiles.getBackIcon(equipCard));
			equipCard.setDetailIcon(DataFiles.getDetailIcon(equipCard));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return equipCard;
	}

	/**
	 * Reads and sets the values of a race card from the CharacterRaceCards.txt file and returns the card
	 */
	public Card loadRaceCard() throws IOException {
		CharacterRaceCard raceCard = new CharacterRaceCard();
		
		String line = this.readLine();
		if(line == null) return null;
		String cardValues[] = line.split(";");
		
		if(cardValues[0].equals("#")){
			return raceCard;
		}
		
		try {
			raceCard.setRace(cardValues[0]);
			raceCard.setLabel(cardValues[1]);
			raceCard.setEscapeLevel(Short.parseShort(cardValues[2]));
			raceCard.setDescription(cardValues[3]);
			raceCard.setCountOfHandCards(Short.parseShort(cardValues[4]));
			raceCard.setSmallIcon(DataFiles.getSmallIcon(raceCard));
			raceCard.setBackIcon(DataFiles.getBackIcon(raceCard));
			raceCard.setDetailIcon(DataFiles.getDetailIcon(raceCard));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return raceCard;
	}

	/**
	 * Reads and sets the values of a class card from the CharacterClassCards.txt file and returns the card
	 */
	public Card loadClassCard() throws IOException {
		CharacterClassCard classCard = new CharacterClassCard(CharacterClassCard.DEFAULT);
		
		String line = this.readLine();
		if(line == null) return null;
		String cardValues[] = line.split(";");
		
		if(cardValues[0].equals("#")){
			return classCard;
		}
		
		try {
			classCard.setCharacterType(cardValues[0]);
			classCard.setLabel(cardValues[1]);
			classCard.setPrimaryAbiltiy(cardValues[2]);
			classCard.setSecondaryAbility(cardValues[3]);
			classCard.setSmallIcon(DataFiles.getSmallIcon(classCard));
			classCard.setBackIcon(DataFiles.getBackIcon(classCard));
			classCard.setDetailIcon(DataFiles.getDetailIcon(classCard));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return classCard;
	}
	
	/**
	 * Reads and sets the values of a buff card from the BuffCards.txt file and returns the card
	 */
	public Card loadBuffCard() throws IOException {
		BuffCard buffCard = new BuffCard();
		
		String line = this.readLine();
		if(line == null) return null;
		String cardValues[] = line.split(";");
		
		if(cardValues[0].equals("#")){
			return buffCard;
		}
		
		try {
			buffCard.setLabel(cardValues[0]);
			buffCard.setDescription(cardValues[1]);
			buffCard.setCombatLevel(Short.parseShort(cardValues[2]));
			buffCard.setPrice(Short.parseShort(cardValues[3]));
			buffCard.setSmallIcon(DataFiles.getSmallIcon(buffCard));
			buffCard.setBackIcon(DataFiles.getBackIcon(buffCard));
			buffCard.setDetailIcon(DataFiles.getDetailIcon(buffCard));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return buffCard;
	}
	
	/**
	 * Reads and sets the values of a curse card from the CurseCards.txt file and returns the card
	 */
	public Card loadCurseCard() throws IOException {
		CurseCard curseCard = new CurseCard();
		
		String line = this.readLine();
		if(line == null) return null;
		String cardValues[] = line.split(";");
		
		if(cardValues[0].equals("#")){
			return curseCard;
		}
		
		try {
			curseCard.setLabel(cardValues[0]);
			curseCard.setDescription(cardValues[1]);
			curseCard.setCurse(cardValues[2]);
			curseCard.setSmallIcon(DataFiles.getSmallIcon(curseCard));
			curseCard.setBackIcon(DataFiles.getBackIcon(curseCard));
			curseCard.setDetailIcon(DataFiles.getDetailIcon(curseCard));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return curseCard;
	}
	
	/**
	 * Reads and sets the values of a monster card from the MonsterCards.txt file and returns the card
	 */
	public Card loadMonsterCard() throws IOException {
		MonsterCard monsterCard = new MonsterCard();
		
		String line = this.readLine();
		if(line == null) return null;
		String cardValues[] = line.split(";");
		
		if(cardValues[0].equals("#")){
			return monsterCard;
		}
		
		try {
			monsterCard.setLabel(cardValues[0]);
			monsterCard.setUndead(Short.parseShort(cardValues[1]));
			monsterCard.setDescription(cardValues[2]);
			monsterCard.setMonsterLevel(Short.parseShort(cardValues[3]));
			monsterCard.setScoreLevel(Short.parseShort(cardValues[4]));
			monsterCard.setCountOfTreasures(Short.parseShort(cardValues[5]));
			monsterCard.setBadThings(cardValues[6]);
			monsterCard.setSmallIcon(DataFiles.getSmallIcon(monsterCard));
			monsterCard.setBackIcon(DataFiles.getBackIcon(monsterCard));
			monsterCard.setDetailIcon(DataFiles.getDetailIcon(monsterCard));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return monsterCard;
	}
	

	/**
	 * Reads and sets the values of a miscellaneous card from the MiscellaneousCards.txt file and returns the card
	 */
	public Card loadMiscellaneousCard() throws IOException {
		MiscellaneousCard miscCard = new MiscellaneousCard();
		
		String line = this.readLine();
		if(line == null) return null;
		String cardValues[] = line.split(";");
		
		if(cardValues[0].equals("#")){
			return miscCard;
		}
		
		try {
			miscCard.setLabel(cardValues[0]);
			miscCard.setDescription(cardValues[1]);
			miscCard.setValue(Short.parseShort(cardValues[2]));
			miscCard.setBig(Short.parseShort(cardValues[3]));
			miscCard.setPrice(Short.parseShort(cardValues[4]));
			miscCard.setInformation(cardValues[5]);
			miscCard.setUsability(cardValues[6]);
			miscCard.setAvailable(Short.parseShort(cardValues[7]));
			miscCard.setSmallIcon(DataFiles.getSmallIcon(miscCard));
			miscCard.setBackIcon(DataFiles.getBackIcon(miscCard));
			miscCard.setDetailIcon(DataFiles.getDetailIcon(miscCard));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return miscCard;
	}

	/**
	 * 
	 */
	public String readLine() throws IOException {
		return reader.readLine();
	}
	
	/**
	 * loads the list of Players and returns the List
	 * @return List<Player>
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<Player> loadPlayers() throws IOException, ClassNotFoundException {
		return (List<Player>) this.ois.readObject();
	}
	
	/**
	 * saves the given Playerlist to a file
	 * @param listOfPlayers
	 */
	@Override
	public void savePlayerList(Vector<Player> listOfPlayers) throws IOException {
		this.oos.writeObject(listOfPlayers);
	}
	
	/**
	 * saves the given Game 
	 * @param gameManagment
	 */
	@Override
	public void saveGame(GameManagement gameManagement) throws IOException {
		this.oos.writeObject(gameManagement);
		this.oos.flush();
	}

	/**
	 * loads the game from file.
	 * @throws ClassNotFoundException
	 * @throws IOException
	 * @return GameManagment
	 */
	@Override
	public GameManagement loadGame() throws ClassNotFoundException, IOException {
		return (GameManagement) this.ois.readObject();
	}


	
}
